﻿namespace TuanHA_Combat_Routine
{
    using Styx;
    using Styx.Common;
    using Styx.CommonBot;
    using Styx.CommonBot.POI;
    using Styx.WoWInternals;
    using Styx.WoWInternals.WoWObjects;
    using System;
    using System.Collections.Generic;
    using System.Runtime.CompilerServices;
    using System.Windows.Media;

    public static class EventHandlers
    {
        private static string CastFailReason;
        public static bool CombatLogAttached;
        private static string LocalizedAnotheractionisinprogress;
        private static string LocalizedLineOfSightError;
        private static HashSet<string> LocalizedShapeshiftErrors;
        private static string LocalizedUnitNotInfrontError;
        private static readonly Dictionary<ulong, int> MobsThatEvaded = new Dictionary<ulong, int>();

        public static void AttachCombatLogEvent()
        {
            if (!CombatLogAttached)
            {
                Lua.Events.AttachEvent("COMBAT_LOG_EVENT_UNFILTERED", new LuaEventHandlerDelegate(EventHandlers.HandleCombatLog));
                if (!Lua.Events.AddFilter("COMBAT_LOG_EVENT_UNFILTERED", "return args[4] == UnitGUID('player') and (args[2] == 'SPELL_MISSED' or args[2] == 'RANGE_MISSED' or args[2] == 'SWING_MISSED')"))
                {
                    Logging.Write("ERROR: Could not add combat log event filter! - Performance may be horrible, and things may not work properly!");
                }
                LocalizedLineOfSightError = Lua.GetReturnVal<string>("return SPELL_FAILED_LINE_OF_SIGHT", 0);
                LocalizedUnitNotInfrontError = Lua.GetReturnVal<string>("return SPELL_FAILED_UNIT_NOT_INFRONT", 0);
                LocalizedAnotheractionisinprogress = Lua.GetReturnVal<string>("return SPELL_FAILED_SPELL_IN_PROGRESS", 0);
                LocalizedShapeshiftErrors = new HashSet<string>();
                LocalizedShapeshiftErrors.Add(Lua.GetReturnVal<string>("return ERR_CANT_INTERACT_SHAPESHIFTED", 0));
                LocalizedShapeshiftErrors.Add(Lua.GetReturnVal<string>("return ERR_MOUNT_SHAPESHIFTED", 0));
                LocalizedShapeshiftErrors.Add(Lua.GetReturnVal<string>("return ERR_NOT_WHILE_SHAPESHIFTED", 0));
                LocalizedShapeshiftErrors.Add(Lua.GetReturnVal<string>("return ERR_NO_ITEMS_WHILE_SHAPESHIFTED", 0));
                LocalizedShapeshiftErrors.Add(Lua.GetReturnVal<string>("return ERR_SHAPESHIFT_FORM_CANNOT_EQUIP", 0));
                LocalizedShapeshiftErrors.Add(Lua.GetReturnVal<string>("return ERR_TAXIPLAYERSHAPESHIFTED", 0));
                LocalizedShapeshiftErrors.Add(Lua.GetReturnVal<string>("return SPELL_FAILED_CUSTOM_ERROR_125", 0));
                LocalizedShapeshiftErrors.Add(Lua.GetReturnVal<string>("return SPELL_FAILED_CUSTOM_ERROR_99", 0));
                LocalizedShapeshiftErrors.Add(Lua.GetReturnVal<string>("return SPELL_FAILED_NOT_SHAPESHIFT", 0));
                LocalizedShapeshiftErrors.Add(Lua.GetReturnVal<string>("return SPELL_FAILED_NO_ITEMS_WHILE_SHAPESHIFTED", 0));
                LocalizedShapeshiftErrors.Add(Lua.GetReturnVal<string>("return SPELL_NOT_SHAPESHIFTED", 0));
                LocalizedShapeshiftErrors.Add(Lua.GetReturnVal<string>("return SPELL_NOT_SHAPESHIFTED_NOSPACE", 0));
                LastLineOfSightError = DateTime.MinValue;
                LastUnitNotInfrontError = DateTime.MinValue;
                LastShapeshiftError = DateTime.MinValue;
                Logging.Write("AttachCombatLogEvent");
                CombatLogAttached = true;
            }
        }

        public static void DetachCombatLogEvent()
        {
            if (CombatLogAttached)
            {
                Logging.Write("DetachCombatLogEvent");
                Logging.Write("Removed combat log filter");
                Lua.Events.RemoveFilter("COMBAT_LOG_EVENT_UNFILTERED");
                Logging.Write("Detached combat log");
                Lua.Events.DetachEvent("COMBAT_LOG_EVENT_UNFILTERED", new LuaEventHandlerDelegate(EventHandlers.HandleCombatLog));
                CombatLogAttached = false;
            }
        }

        private static void HandleCombatLog(object sender, LuaEventArgs args)
        {
            CombatLogEventArgs e = new CombatLogEventArgs(args.EventName, args.FireTimeStamp, args.Args);
            if (e.SourceGuid == StyxWoW.Me.Guid)
            {
                switch (e.Event)
                {
                    case "SPELL_CAST_FAILED":
                        CastFailReason = e.Args[14].ToString();
                        if (((CastFailReason != "Your target is dead") && (CastFailReason != "No target")) && (CastFailReason != "Not yet recovered"))
                        {
                            Logging.Write(Styx.Common.LogLevel.Diagnostic, "[CombatLog] {0} {1}#{2} failure: '{3}'", new object[] { e.Event, e.Spell.Name, e.SpellId, CastFailReason });
                        }
                        return;

                    case "SWING_MISSED":
                        if (e.Args[11].ToString() == "EVADE")
                        {
                            HandleEvadeBuggedMob(args, e);
                            return;
                        }
                        if (e.Args[11].ToString() == "IMMUNE")
                        {
                            WoWUnit destUnit = e.DestUnit;
                            if ((destUnit == null) || destUnit.IsPlayer)
                            {
                                return;
                            }
                            Logging.Write("{0} is immune to Physical spell school", new object[] { destUnit.Name });
                        }
                        return;

                    case "SPELL_MISSED":
                    case "RANGE_MISSED":
                        Logging.Write("[CombatLog] {0} {1}#{2} {3}", new object[] { e.Event, e.Spell.Name, e.SpellId, e.Args[14] });
                        if (e.Args[14].ToString() == "EVADE")
                        {
                            HandleEvadeBuggedMob(args, e);
                            return;
                        }
                        if (e.Args[14].ToString() == "IMMUNE")
                        {
                            WoWUnit unit2 = e.DestUnit;
                            if ((unit2 != null) && !unit2.IsPlayer)
                            {
                                Logging.Write("{0} is immune to {1} spell school", new object[] { unit2.Name, e.SpellSchool });
                            }
                        }
                        return;
                }
                Logging.Write("[CombatLog] filter out this event -- " + e.Event + " - " + e.SourceName + " - " + e.Spell.Name);
            }
        }

        private static void HandleEvadeBuggedMob(LuaEventArgs args, CombatLogEventArgs e)
        {
            WoWUnit destUnit = e.DestUnit;
            ulong destGuid = e.DestGuid;
            if ((destUnit == null) && (StyxWoW.Me.CurrentTarget != null))
            {
                destUnit = StyxWoW.Me.CurrentTarget;
                destGuid = StyxWoW.Me.CurrentTargetGuid;
                Logging.Write("Evade: bugged mob guid:{0}, so assuming current target instead", new object[] { args.Args[7] });
            }
            if (destUnit != null)
            {
                Dictionary<ulong, int> dictionary;
                ulong num2;
                if (!MobsThatEvaded.ContainsKey(destUnit.Guid))
                {
                    MobsThatEvaded.Add(destUnit.Guid, 0);
                }
                (dictionary = MobsThatEvaded)[num2 = destUnit.Guid] = dictionary[num2] + 1;
                if (MobsThatEvaded[destUnit.Guid] <= 5)
                {
                    Logging.Write("Mob {0} has evaded {1} times.  Keeping an eye on {2:X0} for now!", new object[] { destUnit.Name, MobsThatEvaded[destUnit.Guid], destUnit.Guid });
                }
                else
                {
                    if (Blacklist.Contains(destUnit.Guid, BlacklistFlags.Combat))
                    {
                        Logging.Write(Colors.LightGoldenrodYellow, "Mob {0} has evaded {1} times. Previously blacklisted {2:X0} for {3} seconds!", new object[] { destUnit.Name, MobsThatEvaded[destUnit.Guid], destUnit.Guid, 60 });
                    }
                    else
                    {
                        Logging.Write(Colors.LightGoldenrodYellow, "Mob {0} has evaded {1} times. Blacklisting {2:X0} for {3} seconds!", new object[] { destUnit.Name, MobsThatEvaded[destUnit.Guid], destUnit.Guid, 60 });
                        Blacklist.Add(destUnit.Guid, BlacklistFlags.Combat, TimeSpan.FromSeconds(60.0), "");
                        if (!Blacklist.Contains(destUnit.Guid, BlacklistFlags.Combat))
                        {
                            Logging.Write(Colors.Pink, "error: blacklist does not contain entry for {0} so adding {1}", new object[] { destUnit.Name, destUnit.Guid });
                        }
                    }
                    if (BotPoi.Current.Guid == destUnit.Guid)
                    {
                        Logging.Write("EvadeHandling: Current BotPOI type={0} is Evading, clearing now...", new object[] { BotPoi.Current.Type });
                        BotPoi.Clear("Singular recognized Evade bugged mob");
                    }
                    if (StyxWoW.Me.CurrentTargetGuid == destGuid)
                    {
                        foreach (WoWUnit unit2 in Targeting.Instance.TargetList)
                        {
                            if (((unit2 != null) && unit2.IsValid) && (unit2.IsAlive && !Blacklist.Contains(unit2, BlacklistFlags.Combat)))
                            {
                                Logging.Write(Colors.Pink, "Setting target to {0} to get off evade bugged mob!", new object[] { unit2.Name });
                                unit2.Target();
                                return;
                            }
                        }
                        Logging.Write(Colors.Pink, "BotBase has 0 entries in Target list not blacklisted -- nothing else we can do at this point!");
                    }
                }
            }
        }

        private static DateTime LastLineOfSightError
        {
            [CompilerGenerated]
            get
            {
                return <LastLineOfSightError>k__BackingField;
            }
            [CompilerGenerated]
            set
            {
                <LastLineOfSightError>k__BackingField = value;
            }
        }

        private static DateTime LastShapeshiftError
        {
            [CompilerGenerated]
            get
            {
                return <LastShapeshiftError>k__BackingField;
            }
            [CompilerGenerated]
            set
            {
                <LastShapeshiftError>k__BackingField = value;
            }
        }

        private static DateTime LastUnitNotInfrontError
        {
            [CompilerGenerated]
            get
            {
                return <LastUnitNotInfrontError>k__BackingField;
            }
            [CompilerGenerated]
            set
            {
                <LastUnitNotInfrontError>k__BackingField = value;
            }
        }
    }
}

